// 合成复用原则  多组合，少继承
package main

import "fmt"

type CatA struct{}

func (catA CatA) eat() {
	fmt.Println("小猫吃饭...")
}

// CatB 给小猫添加一个睡觉的方法，使用继承方式实现
type CatB struct {
	CatA
}

func (catB *CatB) sleep() {
	fmt.Println("小猫睡觉...")
}

// CatC 给小猫添加一个睡觉的方法，使用组合方式实现1
type CatC struct {
	catA *CatA // 组合进来的一个Cat类
}

func (catC *CatC) eat() {
	catC.catA.eat() // 调用组合进来的原有类的功能
}

func (catC *CatC) sleep() {
	fmt.Println("小猫睡觉...") // 新添加的方法
}

// CatD 给小猫添加一个睡觉的方法，使用组合方式实现2
type CatD struct{}

func (catD *CatD) eat(catA *CatA) {
	catA.eat()
}

func (catD *CatD) sleep() {
	fmt.Println("小猫睡觉...")
}

func main() {
	catA := &CatA{}
	catA.eat()
	fmt.Println("----------")

	// 继承方式实现
	catB := &CatB{}
	catB.eat()
	catB.sleep()
	fmt.Println("----------")

	// 组合方式实现1
	catC := &CatC{catA: &CatA{}}
	catC.eat()
	catC.sleep()
	fmt.Println("----------")

	// 组合方式实现2   <-----推荐写法----->
	catD := &CatD{}
	catD.eat(&CatA{})
	catD.sleep()
}
